#include "DirectInput.h"

// Constructor and Destructor
DirectInput::DirectInput(HWND hWnd, HINSTANCE hInst)
{
	// Call the Initialize method that we created
	this->Initialize( hWnd, hInst );
}

DirectInput::~DirectInput(void)
{
	// Call the Shutdown method that we created
	this->Shutdown();
}

bool DirectInput::Initialize( HWND hWnd, HINSTANCE hInst )
{
	//=============== Initialize DirectInput ==============
	// Create the DirectInput Object
	DirectInput8Create( hInst, DIRECTINPUT_VERSION
		, IID_IDirectInput8, (void**)&m_pDIObject, NULL );

	// Initialize the keyboard
	m_pDIObject->CreateDevice( GUID_SysKeyboard, &m_pDIKeyboard, NULL );

	// Set up the keyboard
	m_pDIKeyboard->SetCooperativeLevel( hWnd
		, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
	m_pDIKeyboard->SetDataFormat( &c_dfDIKeyboard );

	// Initialize the mouse
	m_pDIObject->CreateDevice( GUID_SysMouse, &m_pDIMouse, NULL );

	// Set up the mouse
	m_pDIMouse->SetCooperativeLevel( hWnd
		, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
	m_pDIMouse->SetDataFormat( &c_dfDIMouse2 );

	// Acquire the input devices (keyboard and mouse)
	// If input is lost then acquire and keep trying to acquire
	//  until we get it back
	m_pDIKeyboard->Acquire();
	m_pDIMouse->Acquire();

	// Everything worked so return true
	return true;
}

void DirectInput::Update( HWND hWnd )
{
	//====== Update DirectInput must run on every frame =====
	// Stores the result return by methods
	HRESULT result;

	// Clear the keyboard input buffer
	ZeroMemory( buffer, sizeof(buffer) );

	// Get the current keyboard input device state
	result = m_pDIKeyboard->GetDeviceState( sizeof(buffer)
		, (LPVOID)&buffer );
	if( FAILED(result) )
	{
		// Device has probably been lost if failed
		// so keep trying until we find it
		do
		{
			result = m_pDIKeyboard->Acquire();
		}while( result == DIERR_INPUTLOST );

		// If we failed for some other reason, simply
		//  return out of the method
		if( FAILED(result) )
			return;

		// Read the current keyboard state
		m_pDIKeyboard->GetDeviceState( sizeof(buffer), &buffer );
	}

	// Clear the mouse input buffer
	ZeroMemory( &mouseState, sizeof(mouseState) );

	// Get the mouse input device state
	result = m_pDIMouse->GetDeviceState( sizeof(DIMOUSESTATE2)
		, &mouseState );
	if( FAILED(result) )
	{
		// Device has probably been lost if failed, so keep
		//  trying to get it back until it's found
		do
		{
			result = m_pDIMouse->Acquire();
		}while( result == DIERR_INPUTLOST );

		// If we failed for some other reason, quit the method
		if( FAILED(result) )
			return;

		// Read the current mouse state again
		m_pDIMouse->GetDeviceState( sizeof( DIMOUSESTATE2 )
			, &mouseState );
	}

	// Update the current mouse position
	RECT r;
	GetWindowRect(hWnd, &r);
	POINT p;
	GetCursorPos(&p);
	currentMousePos.x = p.x - r.left;
	currentMousePos.y = p.y - r.top;
}

void DirectInput::Shutdown( void )
{
	//========== Shutdown DirectInput =================
	// Shut down the mouse device
	if( m_pDIMouse )
	{
		m_pDIMouse->Unacquire();
		m_pDIMouse->Release();
		m_pDIMouse = NULL;
	}

	// Shut down the keyboard device
	if( m_pDIKeyboard )
	{
		m_pDIKeyboard->Unacquire();
		m_pDIKeyboard->Release();
		m_pDIKeyboard = NULL;
	}

	// Shut down the DirectInput object
	if( m_pDIObject )
	{
		m_pDIObject->Release();
		m_pDIObject = NULL;
	}
}

bool DirectInput::CheckKeyboard( short key )
{
	// Check to see if the keyboard key is hit
	// DIK stands for DirectInputKeyboard
	// The key received in this mehtod should be
	// one of the DIK constants (enumeration)
	// Read the Keyboard_Device in the documentation
	if( buffer[key] & 0x80 )
	{
		// Key was pressed so return true
		return true;
	}
	else
	{
		// Key was not pressed so return false
		return false;
	}
}

bool DirectInput::CheckMouseButtons( short buttonNumber )
{
	// Check to see if mouse button was hit
	//  0 = Left button
	//  1 = Right button
	//  2 = Middle button ( Scroll wheel pressed )
	//  3-7 = Side buttons
	if( mouseState.rgbButtons[buttonNumber] & 0x80 )
	{
		// Mouse button was pressed
		return true;
	}
	else
	{
		// Mouse button was not pressed
		return false;
	}
}

int DirectInput::CheckMouseMovedX(void)
{
	// Return relative changes
	// you probably want to scale your 1X
	// value so it is not so drastic in your application
	return mouseState.lX;
}

int DirectInput::CheckMouseMovedY(void)
{
	// Return relative changes
	// you probably want to scale your 1Y
	// value so it is not so drastic in your application
	return mouseState.lY;
}

int DirectInput::CheckMouseScroll(void)
{
	// Return relative changes
	// you probably want to scale your 1Z
	// value so it is not so drastic in your application
	return mouseState.lZ;
}